package com.chuanke.ckfamily.service.util;

import com.chuanke.ckfamily.service.common.CacheService;
import com.chuanke.ckfamily.service.common.impl.RedisLockUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public abstract class SynizeThread extends Thread{

    protected CacheService cacheService;

    private String key;

    private long timeout;

    private Long tag;

    private int num;

    private Logger logger = LoggerFactory.getLogger(SynizeThread.class);

    public SynizeThread(CacheService cacheService, String key, long timeout) {
        this.cacheService = cacheService;
        this.key = key;
        this.timeout = timeout;
    }

    public void run() {
        while(true) {
            Long tvalue =  (Long) cacheService.get(key);
            if (!needExecute(tvalue)) {
                logger.info("not need execute ======> tvalue={}", tvalue);
                threadSleep(timeout);
                continue;
            }

            RedisLockUtil lockUtil = null;
            try {
                lockUtil = cacheService.getLock(key.toString());
                tag = System.currentTimeMillis();
                cacheService.set(key, tag);

            } catch (Exception e) {
                threadSleep(1000);
                continue;

            } finally {
                if (lockUtil != null) {
                    lockUtil.unlock();
                }

            }

            try {
                boolean needNext = execute();

                num++;
                if (num > 60) {
                    num = 0;
                    logger.info("execute SynizeThread ======> needNext={}", needNext);
                }

                if (!needNext) {
                    threadSleep(1000);
                }

            } catch (Exception e) {
                threadSleep(1000);

            }
        }
    }

    protected abstract boolean execute();

    private boolean needExecute(Long time) {
        if (time == null) {
            return true;
        }

        if (tag != null && tag.longValue() == time.longValue()) {
            return true;
        }

        logger.debug("is need execute ======>now={} time={}, span={} timeout={}", System.currentTimeMillis(), time, (System.currentTimeMillis() - time), timeout);
        return (System.currentTimeMillis() - time) > timeout;
    }

    private synchronized void threadSleep(long time) {
        try {
            Thread.sleep(time);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
